﻿
////一个数组中只有两个数字是出现一次，其他所有数字都出现了两次。
////编写一个函数找出这两个只出现一次的数字。
//#include<stdio.h>
//void find_two_single(const int* arr, int size, int res[])
//{
//	int n = 0;
//	for (int i = 0; i < size; i++)
//	{
//		int flag = 1;
//		for (int j = 0; j < size; j++)
//		{
//			if (j == i)	 continue;
//			if (*(arr + j) == *(arr + i))
//			{
//				flag = 0;
//				break;
//			}
//		}
//		//printf("flag= %d n= %d \n", flag, n);
//		if (n < 2) {
//			if (flag) {
//				res[n] = *(arr + i);
//				//printf("n= %d res= %d \n", n, res[n]);
//				n++;
//			}
//		}
//		else
//			return;
//	}
//}
//int main()
//{
//	int num[20] = { 1,1,2,2,3,3,4,4,5,5,6,6,7,8,9,9,10,10,11,11 };
//
//	int res[2] = { 0 };
//	find_two_single(num, 20, res);
//
//	for (int i = 0; i < 2; i++)
//	{
//		printf("i= %d res= %d \n", i, res[i]);
//	}
//
//	return 0;
//}


////模拟实现strncpy
//#include<stdio.h>
//#include<assert.h>
//char* my_strncpy(char* destination, const char* source, size_t num)
//{
//	assert(destination && source);
//
//	char* res = destination;
//	for (int i = 0; i < num; i++)
//	{
//		*(destination + i) = *(source + i);
//	}
//	return res;
//}
//int main()
//{
//	char str1[] = "*****************";
//	char str2[] = "hello,my!";
//
//	printf("%s\n", my_strncpy(str1, str2, 10));
//
//
//	return 0;
//}


////模拟实现strncat
//#include<stdio.h>
//#include<assert.h>
//char* my_strncat(char* destination, const char* source, size_t num)
//{
//	assert(destination && source);
//
//	char* res = destination;
//	while (*destination)
//	{
//		destination++;
//	}
//
//	for (int i = 0; i < num; i++)
//	{
//		*(destination + i) = *(source + i);
//	}
//	int i = 0;
//	while (i < num && *source)
//	{
//		*destination = *source;
//		destination++;
//		source++;
//		i++;
//	}
//	return res;
//}
//int main()
//{
//	char str1[40] = "*****************";
//	char str2[] = "hello,my!";
//
//	printf("%s\n", my_strncat(str1, str2, 5));
//
//
//	return 0;
//}


////模拟实现atoi
//#include<stdio.h>
//int my_atoi(const char* str)
//{
//	int num = 0;
//	while (*str)
//	{
//		if (*str >= '0' && *str <= '9') //字符是表示数字的字符 
//		{
//			num = num * 10 + (*str - '0');
//		}
//		str++;
//	}
//	return num;
//}
//int main()
//{
//
//	char arr[10] = "123456";
//
//	printf("%d\n", my_atoi(arr));
//
//	return 0;
//}

//在X86下，小端字节序存储，有下列程序
//union只有2字节，2字节的十六进制只有4位。
// 而位顺序类似小端，低地址在低处，
// 所以39是低地址，在低位，
// 38在高位，所以是3839
//#include<stdio.h>
//int main()
//{
//    union
//    {
//        short k;
//        char i[2];
//    }*s, a;
//    s = &a;
//    s->i[0] = 0x39;//先存放在低地址
//    s->i[1] = 0x38;//存放在高地址？
//    printf(" %x\n", a.k);//小端存储，从高地址往低地址取出数据
//    return 0;
//}


//一个数组中只有两个数字是出现一次，其他所有数字都出现了两次。
//找出一个只出现过一次的数字的问题处理方法就是找一个数字把里面所有的数字都异或一遍，
//利用异或两次等于没异或的特点来处理。
//那么如果有两个数字都只出现了一次，那么如此得到的应该是两个数异或的结果。
//首先这个结果肯定不是0（要不然就全都配对了），所以里面一定至少一位是一。
//找出值为1的一位，以这一位的值将结果分为两组。
//例如1 2 3 4 1 2，异或完的结果应该是3^4得到的111，那么随便找一位就行了。
//例如找最低位，那么这一位是1的有1 3 1，是0的有2 4 2，
//由于是利用异或结果为1的某一位分的组，所以两个待查询数字一定分别在两组中。
//所以再找两个变量，分别异或两组数，即可找到这两个数。
void findTwoNum(int arr[], int n, int* pnum1, int* pnum2)
{
	int i;
	int sum = 0;
	for (i = 0; i < 9; i++)
	{
		sum ^= arr[i];
	} //先找到两个数互相异或的结果
	int pos;
	for (i = 0; i < 32; i++)
	{
		if (sum & 1 << i)
		{
			pos = i;
			break;
		}
	} //再找到有分歧的一位。在这一位上，两个数一定是一个1一个0
	
	* pnum1 = *pnum2 = 0;
	for (i = 0; i < 10; i++)
	{
		if (arr[i] & 1 << pos)
		{
			*pnum1 ^= arr[i]; //这一位是1的，放在数1里
		}
		else
		{
			*pnum2 ^= arr[i]; //这一位是0的，放在数2里
		}
	}
}
